/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package gride.plugin.error;

import gride.project.ProjectManager;


/**
 *
 * @author lukasz
 */
public class ErrorDescription
{
    private boolean compileTime;

    private String exceptionType = null;
    private String exceptionMessage = null;

    private String className = null;
    private String methodName = null;
    private String filename = null;
    private int lineNumber = -1;

    private String shortStackTrace = null;
    private String fullStackTrace = null;

    private ProjectManager projectManager;

    /**
     *
     * @param projectManager
     * @param message
     */
    public ErrorDescription(ProjectManager projectManager, String message)
    {
        this.projectManager = projectManager;

        try
        {
            compileTime = true;
            exceptionType = message.substring(0, message.indexOf(":"));
            exceptionType =
                    exceptionType.substring(exceptionType.lastIndexOf(".") + 1);

            message = message.replace(exceptionType + ":", "").trim();

            // parse exception message
            parseCompileMessage(message);
        }
        catch (Exception e)
        {
            // message couldn't be parsed
        }
    }

    /**
     *
     * @param projectManager
     * @param e
     */
    public ErrorDescription(ProjectManager projectManager, Exception e)
    {
        this.projectManager = projectManager;

        // first of all, check if this is a compilation or runtime error
        if (e instanceof org.codehaus.groovy.control.CompilationFailedException)
            compileTime = true;            

        try
        {
            if (!compileTime)
            {
                boolean foundTop = false;

                // get the type of the exception which was the original cause
                if (e.getCause() != null)
                    exceptionType = e.getCause().getClass().toString().
                                                          replace("class ", "");
                else
                    exceptionType = e.getClass().toString().
                                                          replace("class ", "");


                // get the exception message
                if (e.getMessage().indexOf(":") >= 0)
                    exceptionMessage = e.getMessage().substring(
                                        e.getMessage().indexOf(":") + 1).trim();

                // get the exception stack trace
                StringBuilder full = new StringBuilder();
                StringBuilder shrt = new StringBuilder();

                StackTraceElement[] stackTrace;
                if (e.getCause() != null)
                    stackTrace = e.getCause().getStackTrace();
                else
                    stackTrace = e.getStackTrace();

                for (StackTraceElement ste : stackTrace)
                {
                    String s = ste.getClassName() + "." + ste.getMethodName() +
                               " (in file " + ste.getFileName() + " line " +
                               ste.getLineNumber() + ")\n";

                    full.append(s);

                    // for the short version of the stack, don't display frames
                    // related to Groovy execution or Gride itself
                    if (!s.startsWith("java.lang.reflect") &&
                        !s.startsWith("sun.reflect") &&
                        !s.startsWith("groovy.lang") &&
                        !s.startsWith("org.codehaus") &&
                        !s.startsWith("gride"))
                    {
                        // the first frame that matches our criteria will be
                        // the top of our filtered stack
                        if (!foundTop)
                        {
                            className = ste.getClassName();
                            methodName = ste.getMethodName();
                            filename = ste.getFileName();
                            lineNumber = ste.getLineNumber();

                            if (className.contains("."))
                            {
                                String pack =
                                     className.substring(0, 
                                                    className.lastIndexOf(".")).
                                                    replace(".", "/");

                                filename = pack + "/" + filename;
                            }

                            foundTop = true;
                        }

                        if (lineNumber == -1)
                            lineNumber = ste.getLineNumber();

                        shrt.append(s);
                    }
                }

                fullStackTrace = full.toString();
                shortStackTrace = shrt.toString();
            }
            else // compile time exception
            {
                // get the type of the exception which was the original cause
                exceptionType = e.getClass().toString();
                exceptionType =
                        exceptionType.substring(exceptionType.lastIndexOf(".")
                                                + 1);

                // parse the exception message
                parseCompileMessage(e.getMessage());
            }
        }
        catch (Exception ex)
        {
            // the exception couldn't be parsed
        }
    }

    /**
     *
     * @return
     */
    public boolean isCompileTime()
    {
        return compileTime;
    }

    /**
     *
     * @return
     */
    public String getExceptionType()
    {
        return exceptionType;
    }

    /**
     *
     * @return
     */
    public String getExceptionMessage()
    {
        return exceptionMessage;
    }

    /**
     *
     * @return
     */
    public String getClassName()
    {
        return className;
    }

    /**
     *
     * @return
     */
    public String getMethodName()
    {
        return methodName;
    }

    /**
     *
     * @return
     */
    public String getFilename()
    {
        return filename;
    }

    /**
     *
     * @return
     */
    public int getLineNumber()
    {
        return lineNumber;
    }

    /**
     *
     * @return
     */
    public String getFullStackTrace()
    {
        return fullStackTrace;
    }

    /**
     *
     * @return
     */
    public String getShortStackTrace()
    {
        return shortStackTrace;
    }


    private void parseCompileMessage(String message)
    {
        filename = message.substring(message.indexOf(", "),
                                     message.indexOf(":"))
                          .replace(",", "").trim();

        String srcDir =
                    projectManager.getCurrentProject().getSourceDir().getPath();
        filename = filename.replace(srcDir + "/", "");

        message = message.replace(message.substring(0, message.indexOf(":")),
                                                                            "");
        message = message.substring(1);

        lineNumber = Integer.parseInt(
                             message.substring(0, message.indexOf(":")).trim());

        exceptionMessage = message.substring(message.indexOf(":") + 2);
    }

}
